package main

import (
	agent_model "agent/agent-model"
	"agent/agent-service"
	"agent/utils"
	"bufio"
	"context"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/cloudwego/eino-ext/components/model/openai"
	"github.com/cloudwego/eino/schema"
)

// 全局变量
var (
	chatModel   *openai.ChatModel
	chatHistory []*schema.Message
	reader      *bufio.Reader
	jokeAgent   *agent_service.JokeAgent
)

// 主函数 - AI Agent 应用入口
// 功能：实现交互式AI对话系统，支持连续提问、对话历史管理和安全退出
func main() {
	// 初始化应用
	ctx := context.Background()
	initializeApp(ctx)

	// 初始化笑话智能体
	jokeAgent = agent_service.NewJokeAgent(chatModel)

	// 显示欢迎信息
	utils.ShowWelcomeMessage()

	// 运行主循环
	runMainLoop(ctx)
}

// initializeApp 初始化应用程序组件
func initializeApp(ctx context.Context) {
	log.Println("正在初始化模型...")
	//chatModel = agent_model.NewDeepseekV3Model()
	chatModel = agent_model.NewDoubao32kModel()
	chatHistory = make([]*schema.Message, 0)
	reader = bufio.NewReader(os.Stdin)
}

// handleConversation 处理正常对话流程
func handleConversation(ctx context.Context, userInput string) {
	// 检查用户输入是否为空
	if userInput == "" {
		fmt.Println("输入不能为空，请重试")
		return
	}

	log.Printf("用户输入内容: %s\n", userInput)

	// 添加用户消息到对话历史
	addUserMessage(userInput)

	// 限制对话历史长度
	limitChatHistory()

	// 生成并显示回复
	generateAndShowResponse(ctx)
}

// addUserMessage 将用户消息添加到对话历史
func addUserMessage(content string) {
	userMessage := &schema.Message{
		Role:    schema.User,
		Content: content,
	}
	chatHistory = append(chatHistory, userMessage)
}

// limitChatHistory 限制对话历史长度，避免上下文过长
func limitChatHistory() {
	const maxHistoryLength = 20
	if len(chatHistory) > maxHistoryLength {
		chatHistory = chatHistory[len(chatHistory)-maxHistoryLength:]
		log.Println("对话历史过长，已自动裁剪")
	}
}

// generateAndShowResponse 生成并显示模型回复
func generateAndShowResponse(ctx context.Context) {
	log.Println("正在生成回复...")
	resp, err := chatModel.Generate(ctx, chatHistory)
	if err != nil {
		log.Printf("[错误] 生成回复失败: %v\n", err)
		fmt.Println("生成回复失败，请重试...")
		// 移除刚刚添加的用户消息，因为请求失败了
		chatHistory = chatHistory[:len(chatHistory)-1]
		return
	}

	// 检查resp是否为nil
	if resp == nil {
		log.Println("[错误] 模型返回了空回复")
		fmt.Println("模型未返回任何内容，请重试...")
		chatHistory = chatHistory[:len(chatHistory)-1]
		return
	}

	// 将模型回复添加到对话历史
	chatHistory = append(chatHistory, resp)

	// 输出结果
	log.Println("成功获取模型回复")
	fmt.Println("\n模型回复:")
	if resp.Content != "" {
		fmt.Println(resp.Content)
	} else {
		fmt.Println("[空回复内容]")
	}
	log.Printf("当前对话历史长度: %d\n", len(chatHistory))
}

// 定义命令常量
const (
	ExitCommand  = "exit"
	QuitCommand  = "quit"
	ClearCommand = "clear"
)

// runMainLoop 运行主对话循环
func runMainLoop(ctx context.Context) {
	for {
		// 获取用户输入
		userInput := getUserInput()
		if userInput == "" {
			continue
		}

		// 处理特殊命令和笑话请求
		isSpecialCommand, isJokeRequest := handleSpecialCommandsAndJokes(userInput)

		// 如果是退出命令，退出循环
		if isSpecialCommand {
			break
		}

		// 如果是笑话请求，跳过正常对话处理
		if isJokeRequest {
			continue
		}

		// 处理正常对话
		handleConversation(ctx, userInput)
	}

	log.Println("应用程序已正常退出")
}

// getUserInput 获取并清理用户输入
func getUserInput() string {
	fmt.Print("\n> 请输入: ")
	userInput, err := reader.ReadString('\n')
	if err != nil {
		log.Printf("[错误] 读取用户输入失败: %v\n", err)
		fmt.Println("读取输入失败，请重试...")
		return ""
	}

	// 去除输入内容的前后空白字符
	return strings.TrimSpace(userInput)
}

// handleSpecialCommandsAndJokes 处理特殊命令和笑话请求
// 返回两个布尔值：第一个表示是否是退出命令，第二个表示是否是笑话请求
func handleSpecialCommandsAndJokes(input string) (bool, bool) {
	// 首先尝试使用笑话智能体处理输入
	result, isJokeRequest, err := jokeAgent.HandleUserInput(context.Background(), input)
	if err != nil {
		log.Printf("处理笑话请求失败: %v", err)
		fmt.Printf("处理笑话请求时发生错误: %v\n", err)
		return false, false
	}

	// 如果是笑话相关请求，直接输出结果
	if isJokeRequest {
		fmt.Println("\n笑话回复:")
		fmt.Println(result)
		return false, true
	}

	// 转换为小写以进行不区分大小写的匹配
	lowerInput := strings.ToLower(input)

	switch lowerInput {
	case ExitCommand, QuitCommand:
		log.Println("用户请求退出程序")
		fmt.Println("\n感谢使用AI Agent，再见！")
		return true, false
	case ClearCommand:
		log.Println("用户请求清空对话历史")
		chatHistory = make([]*schema.Message, 0)
		fmt.Println("对话历史已清空")
		return false, false
	default:
		return false, false
	}
}
